home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / unixcpio.gz / unixnet.cpio / ax25.c < prev    next >
C/C++ Source or Header  |  1994-07-11  |  13KB  |  432 lines

  1. /* Low level AX.25 frame processing - address header */
  2.  
  3. #include <stdio.h>
  4. #include <time.h>
  5. #include "config.h"
  6. #include "global.h"
  7. #include "mbuf.h"
  8. #include "iface.h"
  9. #include "timer.h"
  10. #include "arp.h"
  11. #include "slip.h"
  12. #include "ax25.h"
  13. #include "lapb.h"
  14. #include <ctype.h>
  15. #include "heard.h"
  16. #ifdef    UNIX
  17. #include <memory.h>
  18. #include <sys/types.h>
  19. time_t time();
  20. #endif
  21.  
  22. #ifdef MULPORT
  23. extern int mport;
  24. #endif
  25.  
  26. /* AX.25 broadcast address: "QST-0" in shifted ascii */
  27. struct ax25_addr ax25_bdcst = {
  28.      'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1,
  29.      ('0'<<1) | E,
  30. };
  31. #ifdef SID2
  32. struct ax25_addr bbscall;
  33. #endif
  34. char axbdcst[AXALEN];    /* Same thing, network format */
  35. struct ax25_addr mycall;
  36. int digipeat = 1;   /* Controls digipeating */
  37.  
  38. /* Send IP datagrams across an AX.25 link */
  39. /*ARGSUSED*/
  40. int
  41. ax_send(bp,interface,gateway,precedence,delay,throughput,reliability)
  42. struct mbuf *bp;
  43. struct interface *interface;
  44. int32 gateway;
  45. char precedence;
  46. char delay;
  47. char throughput;
  48. char reliability;
  49. {
  50.      char *hw_addr,*res_arp();
  51.      struct ax25_cb *axp,*find_ax25(),*open_ax25();
  52.      struct ax25 addr;
  53.      struct ax25_addr destaddr;
  54.      struct mbuf *tbp;
  55.      extern int16 axwindow;
  56.      void ax_incom();
  57.      int16 size,bsize,seq;
  58.  
  59.      if((hw_addr = res_arp(interface,ARP_AX25,gateway,bp)) == NULLCHAR)
  60.           return 0; /* Wait for address resolution */
  61.  
  62.      if(delay || (!reliability && (interface->flags == DATAGRAM_MODE))){
  63.           /* Use UI frame */
  64.           return (*interface->output)(interface,hw_addr,
  65.                interface->hwaddr,PID_FIRST|PID_LAST|PID_IP,bp);
  66.      }
  67.      /* Reliability is needed; use I-frames in AX.25 connection */
  68.      memcpy(destaddr.call,hw_addr,ALEN);
  69.      destaddr.ssid = hw_addr[ALEN];
  70.  
  71.      if((axp = find_ax25(&destaddr)) == NULLAX25 || (axp->state != CONNECTED && axp->state!=RECOVERY)){
  72.           /*NOTE: ADDED W9NK's SABM FIX OF && AXP->STATE!=RECOVERY GRC*/
  73.           /* Open a new connection or reinitialize the old one */
  74.           atohax25(&addr,hw_addr,(struct ax25_addr *)interface->hwaddr);
  75.           axp = open_ax25(&addr,axwindow,ax_incom,NULLVFP,NULLVFP,interface,(char *)0);
  76.           if(axp == NULLAX25){
  77.                free_p(bp);
  78.                return -1;
  79.           }
  80.      }
  81.      /* If datagram is too big for one frame, send all but the last with
  82.       * the extension PID. Note: the copy to a new buf is necessary because
  83.       * AX.25 may continue retransmitting the frame after a local TCB has
  84.       * gone away, and using the buf directly would cause heap garbage to be
  85.       * transmitted. Besides, nobody would ever use AX.25 anywhere
  86.       * high performance is needed anyway...
  87.       */
  88.      bsize = len_mbuf(bp);
  89.      seq = 0;
  90.      while(bsize != 0){
  91.           size = min(bsize,axp->paclen);
  92.           /* Allocate buffer, allowing space for PID */
  93.           if((tbp = alloc_mbuf(size + 1)) == NULLBUF)
  94.                break;         /* out of memory! */
  95.           *tbp->data = PID_IP;
  96.           if(seq++ == 0)
  97.                *tbp->data |= PID_FIRST;  /* First in sequence */
  98.           if(size == bsize)
  99.                *tbp->data |= PID_LAST;       /* That's all of it */
  100.           /* else more to follow */
  101.  
  102.           tbp->cnt = 1;
  103.           tbp->cnt += pullup(&bp,tbp->data + 1,size);
  104.           send_ax25(axp,tbp);
  105.           bsize -= size;
  106.      }
  107.      free_p(bp);    /* Shouldn't be necessary */
  108.      return 0;
  109. }
  110. /* Add AX.25 link header and send packet.
  111.  * Note that the calling order here must match ec_output
  112.  * since ARP also uses it.
  113.  */
  114. int
  115. ax_output(interface,dest,source,pid,data)
  116. struct interface *interface;
  117. char *dest;         /* Destination AX.25 address (7 bytes, shifted) */
  118.                /* Also includes digipeater string */
  119. char *source;       /* Source AX.25 address (7 bytes, shifted) */
  120. char pid;      /* Protocol ID */
  121. struct mbuf *data;  /* Data field (follows PID) */
  122. {
  123.      struct mbuf *abp,*cbp,*htonax25();
  124.      struct ax25 addr;
  125.  
  126.      /* Allocate mbuf for control and PID fields, and fill in */
  127.      if((cbp = pushdown(data,2)) == NULLBUF){
  128.           free_p(data);
  129.           return -1;
  130.      }
  131.      cbp->data[0] = UI;
  132.      cbp->data[1] = pid;
  133.  
  134.      atohax25(&addr,dest,(struct ax25_addr *)source);
  135.      if((abp = htonax25(&addr,cbp)) == NULLBUF){
  136.           free_p(cbp);   /* Also frees data */
  137.           return -1;
  138.      }
  139.      /* This shouldn't be necessary because redirection has already been
  140.       * done at the IP router layer, but just to be safe...
  141.       */
  142.      if(interface->forw != NULLIF)
  143.           return (*interface->forw->raw)(interface->forw,abp);
  144.      else
  145.           return (*interface->raw)(interface,abp);
  146. }
  147. /* Process incoming AX.25 packets.
  148.  * After optional tracing, the address field is examined. If it is
  149.  * directed to us as a digipeater, repeat it.  If it is addressed to
  150.  * us or to QST-0, kick it upstairs depending on the protocol ID.
  151.  */
  152. int
  153. ax_recv(interface,bp)
  154. struct interface *interface;
  155. struct mbuf *bp;
  156. {
  157. #ifdef MULPORT
  158.      struct interface *repeater();
  159. #endif
  160.      void arp_input();
  161.      int ip_route();
  162.      struct ax25_addr *ap;
  163.      struct mbuf *htonax25(),*hbp;
  164.      char multicast;
  165.      int nrnodes = 0;
  166.      char control;
  167.      struct ax25 hdr;
  168.      struct ax25_cb *axp,*find_ax25(),*cr_ax25();
  169.      struct ax25_addr ifcall;
  170.      extern struct ax25_addr nr_nodebc ;
  171. /* heard stuff */
  172.      struct heard_stuff *hp;
  173.      extern struct ax25_heard heard;
  174.      int16 type, ftype();
  175.      int prev, curr;
  176. /* heard stuff */
  177.  
  178.      /* Use the address associated with this interface */
  179.      memcpy(ifcall.call,interface->hwaddr,ALEN);
  180.      ifcall.ssid = interface->hwaddr[ALEN];
  181.  
  182.      /* Pull header off packet and convert to host structure */
  183.      if(ntohax25(&hdr,&bp) < 0){
  184.           /* Something wrong with the header */
  185.           free_p(bp);
  186.           return;
  187.      }
  188. /* heard stuff */
  189.     if (heard.enabled) {
  190.         /* scan heard list.  if not there, add it */
  191.         prev = -1;
  192.         curr = heard.first;
  193.         while (1) {
  194.             if (curr != -1) {
  195.                 hp = &heard.list[curr];
  196.                 if (addreq(&hp->info.source, &hdr.source)) {
  197.                     time(&hp->htime);
  198.                     /* if not the first, make it so */
  199.                     if (prev != -1) {
  200.                         heard.list[prev].next = hp->next;
  201.                         hp->next = heard.first;
  202.                         heard.first = curr;
  203.                     }
  204.                     break;
  205.                 }
  206.             }
  207.  
  208.             /* if the last one, add another if room, or overwrite it */
  209.             if (curr == -1 || hp->next == -1) {
  210.                 /* not in heard list, add it.  if no room, bump oldest */
  211.                 if (heard.cnt < MAX_HEARD) {
  212.                     heard.list[heard.cnt].next = heard.first;
  213.                     heard.first = heard.cnt;
  214.                     hp = &heard.list[heard.cnt++];
  215.                 } else {
  216.                     heard.list[prev].next = -1;
  217.                     heard.list[curr].next = heard.first;
  218.                     heard.first = curr;
  219.                     hp = &heard.list[curr];
  220.                 }
  221.                 hp->flags = 0;
  222.                 memcpy(&hp->info, &hdr, sizeof(struct ax25));
  223.                 time(&hp->htime);
  224.                 break;
  225.             }
  226.     
  227.             prev = curr;
  228.             curr = hp->next;
  229.         }
  230.         
  231.         /* figure out what the other station is running */
  232.         if (bp->cnt >= 2) {
  233.             type = ftype(*bp->data);
  234.             if(type == I || type == UI){    
  235.                 switch(*(bp->data + 1) & 0x3f){
  236.                 case PID_ARP:
  237.                     hp->flags |= HEARD_ARP;
  238.                     break;
  239.                 case PID_NETROM:
  240.                     hp->flags |= HEARD_NETROM;
  241.                     break;
  242.                 case PID_IP:
  243.                     hp->flags |= HEARD_IP;
  244.                     break;
  245.                 }
  246.             }
  247.         }
  248.     } else {
  249.         hp = NULL;
  250.     }
  251. /* heard stuff */
  252.      /* Scan, looking for our call in the repeater fields, if any.
  253.       * Repeat appropriate packets.
  254.       */
  255.      for(ap = &hdr.digis[0]; ap < &hdr.digis[hdr.ndigis]; ap++){
  256.           if(ap->ssid & REPEATED)
  257.                continue; /* Already repeated */
  258.           /* Check if packet is directed to us as a digipeater */
  259.           if(digipeat && addreq(ap,&ifcall)){
  260.                /* Yes, kick it back out */
  261. #ifdef MULPORT
  262. /****************************************************************************
  263. *                 Multiport repeater hack by KE4ZV                          *
  264. ****************************************************************************/
  265.           if (mport){
  266.               interface=repeater(ap,interface,&hdr);
  267.              }
  268. /****************************************************************************
  269. *                  Multiport repeater hack ends                             *
  270. ****************************************************************************/
  271. #endif
  272.                ap->ssid |= REPEATED;
  273.                if((hbp = htonax25(&hdr,bp)) != NULLBUF){
  274.                     if(interface->forw != NULLIF)
  275.                          (*interface->forw->raw)(interface->forw,hbp);
  276.                     else
  277.                          (*interface->raw)(interface,hbp);
  278.                     bp = NULLBUF;
  279.                }
  280.           }
  281.           free_p(bp);    /* Dispose if not forwarded */
  282.           return;
  283.      }
  284.      /* Packet has passed all repeaters, now look at destination */
  285.      if(addreq(&hdr.dest,&ax25_bdcst)){
  286.           multicast = 1; /* Broadcast packet */
  287. #ifdef SID2
  288.      } else if(addreq(&hdr.dest,&ifcall) || addreq(&hdr.dest,&bbscall)){
  289. #else
  290.      } else if(addreq(&hdr.dest,&ifcall)){
  291. #endif
  292.           multicast = 0; /* Packet directed at us */
  293.      } else if(addreq(&hdr.dest,&nr_nodebc)){
  294.           nrnodes = 1 ;
  295.      } else {
  296.           /* Not for us */
  297.           free_p(bp);
  298.           return;
  299.      }
  300.      if(bp == NULLBUF){
  301.           /* Nothing left */
  302.           return;
  303.      }
  304.      /* Sneak a peek at the control field. This kludge is necessary because
  305.       * AX.25 lacks a proper protocol ID field between the address and LAPB
  306.       * sublayers; a control value of UI indicates that LAPB is to be
  307.       * bypassed.
  308.       */
  309.      control = *bp->data & ~PF;
  310.      if(uchar(control) == UI){
  311.           char pid;
  312.  
  313.           (void) pullchar(&bp);
  314.           if(pullup(&bp,&pid,1) != 1)
  315.                return;        /* No PID */
  316.           /* NET/ROM is very poorly layered. The meaning of the stuff
  317.            * following the PID of CF depends on what's in the AX.25 dest
  318.            * field.
  319.            */
  320.           if(nrnodes){
  321.                if(uchar(pid) == (PID_NETROM | PID_FIRST | PID_LAST))
  322.                     nr_nodercv(interface,&hdr.source,bp) ;
  323.                else      /* regular UI packets to "nodes" aren't for us */
  324.                     free_p(bp) ;
  325.                return ;
  326.           }
  327.           /* Handle packets. Multi-frame messages are not allowed */
  328.           switch(pid & (PID_FIRST | PID_LAST | PID_PID)){
  329.           case (PID_IP | PID_FIRST | PID_LAST):
  330.                ip_route(bp,multicast);
  331.                break;
  332.           case (PID_ARP | PID_FIRST | PID_LAST):
  333.                arp_input(interface,bp);
  334.                break;
  335.           default:
  336.                free_p(bp);
  337.                break;
  338.           }
  339.           return;
  340.      }
  341.      /* Everything from here down is LAPB stuff, so drop anything
  342.       * not directed to us:
  343.       */
  344.  
  345.      if (multicast || nrnodes) {
  346.           free_p(bp) ;
  347.           return ;
  348.      }
  349.  
  350.      /* Find the source address in hash table */
  351.      if((axp = find_ax25(&hdr.source)) == NULLAX25){
  352.           /* Create a new ax25 entry for this guy,
  353.            * insert into hash table keyed on his address,
  354.            * and initialize table entries
  355.            */
  356.           if((axp = cr_ax25(&hdr.source)) == NULLAX25){
  357.                free_p(bp);
  358.                return;
  359.           }
  360.           axp->interface = interface;
  361.           /* Swap source and destination, reverse digi string */
  362.           ASSIGN(axp->addr.dest,hdr.source);
  363.           ASSIGN(axp->addr.source,hdr.dest);
  364.           if(hdr.ndigis > 0){
  365.                int i,j;
  366.  
  367.                /* Construct reverse digipeater path */
  368.                for(i=hdr.ndigis-1,j=0;i >= 0;i--,j++){
  369.                     ASSIGN(axp->addr.digis[j],hdr.digis[i]);
  370.                     axp->addr.digis[j].ssid &= ~(E|REPEATED);
  371.                }
  372.                /* Scale timers to account for extra delay */
  373.                axp->t1.start *= hdr.ndigis+1;
  374.                axp->t2.start *= hdr.ndigis+1;
  375.                axp->t3.start *= hdr.ndigis+1;
  376.           }
  377.           axp->addr.ndigis = hdr.ndigis;
  378.      }
  379.      if(hdr.cmdrsp == UNKNOWN)
  380.           axp->proto = V1;    /* Old protocol in use */
  381.      else
  382.           axp->proto = V2;
  383.  
  384.      lapb_input(axp,hdr.cmdrsp,bp);
  385. }
  386. /* Initialize AX.25 entry in arp device table */
  387. /* General purpose AX.25 frame output */
  388. int
  389. sendframe(axp,cmdrsp,ctl,data)
  390. struct ax25_cb *axp;
  391. char cmdrsp;
  392. char ctl;
  393. struct mbuf *data;
  394. {
  395.      struct mbuf *hbp,*cbp,*htonax25();
  396.      int i;
  397.  
  398.      if(axp == NULLAX25 || axp->interface == NULLIF)
  399.           return -1;
  400.  
  401.      /* Add control field */
  402.      if((cbp = pushdown(data,1)) == NULLBUF){
  403.           free_p(data);
  404.           return -1;
  405.      }
  406.      cbp->data[0] = ctl;
  407.  
  408.      axp->addr.cmdrsp = cmdrsp;
  409.      /* Create address header */
  410.      if((hbp = htonax25(&axp->addr,cbp)) == NULLBUF){
  411.           free_p(cbp);
  412.           return -1;
  413.      }
  414.      /* The packet is all ready, now send it */
  415.      if(axp->interface->forw != NULLIF)
  416.           i = (*axp->interface->forw->raw)(axp->interface->forw,hbp);
  417.      else
  418.           i = (*axp->interface->raw)(axp->interface,hbp);
  419.  
  420.      return i;
  421. }
  422. axarp()
  423. {
  424.      int psax25(),setpath();
  425.  
  426.      memcpy(axbdcst,ax25_bdcst.call,ALEN);
  427.      axbdcst[ALEN] = ax25_bdcst.ssid;
  428.  
  429.      arp_init(ARP_AX25,AXALEN,PID_FIRST|PID_LAST|PID_IP,
  430.       PID_FIRST|PID_LAST|PID_ARP,axbdcst,psax25,setpath);
  431. }
  432.